﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using VirtualPress.Tool.Framework;

namespace VirtualPress.Infrastructure.HitMonitor
{
    public class HitMonitor : IDisposable
    {
        private HitMonitor() { }
        private static HitMonitor instance = null;
        private Dictionary<string, BaseMonitor> memory;
        private int interval = 
#if DEBUG
            1 * 60 * 1000;
#else
            10 * 60 * 1000;
#endif
        static HitMonitor()
        {
            instance = new HitMonitor();
            instance.init();
        }
        public void init()
        {
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Enabled = true;
            timer.Interval = interval;
            timer.Elapsed += new System.Timers.ElapsedEventHandler((o, e) =>
            {
#if DEBUG
                LogHelper.Write(CommonLogger.ExServer, LogLevel.Info, "HitMonitor is working!");
#endif
                if (memory != null)
                {
                    foreach (var item in memory)
                    {
                        try
                        {
                            Monitor.Enter(item.Value);
                            item.Value.Flush();
                            Monitor.Exit(item.Value);
                        }
                        catch (Exception exp)
                        {
                            LogHelper.Write(CommonLogger.ExServer, LogLevel.Error, exp);
                        }
                    }
                }
            });
            timer.AutoReset = true;
            memory = new Dictionary<string, BaseMonitor>();
        }
        
        public static BaseMonitor Instance(HitName name, object key)
        {
            string dictKey = GetHitMonitorName(name, key);
            if (String.IsNullOrEmpty(dictKey))
            {
                throw new Exception("点击管理器获取对象异常");
            }
            if (!instance.memory.Keys.Contains(dictKey))
            {
                Monitor.Enter(instance.memory);
                if (!instance.memory.Keys.Contains(dictKey))
                {
                    switch (name)
                    {
                        case HitName.Journal:
                            instance.memory.Add(dictKey, new JournalHitMonitor(key));
                            break;
                        case HitName.Article:
                            instance.memory.Add(dictKey, new ArticleHitMonitor(key));
                            break;
                        case HitName.Meeting:
                            instance.memory.Add(dictKey, new MeetingHitmonitor(key));
                            break;
                    }
                }
                Monitor.Exit(instance.memory);
            }
            return instance.memory[dictKey];
        }
        private static string GetHitMonitorName(HitName name,object key)
        {
            switch (name)
            { 
                case HitName.Journal:
                    return JournalHitMonitor.GetMemoryKey(key);
                case HitName.Article:
                    return ArticleHitMonitor.GetMemoryKey(key);
                case HitName.Meeting:
                    return MeetingHitmonitor.GetMemoryKey(key);
            }
            return string.Empty;
        }
        public static void Close()
        {
            instance.Dispose();
        }
        public void Dispose()
        {
            if(memory!= null)
            {
                Monitor.Enter(memory);
                foreach (var item in memory)
                {
                    item.Value.Dispose();
                }
                memory.Clear();
                Monitor.Exit(memory);
            }
        }
    }
    public enum HitName
    {
        Journal,
        Meeting,
        Article
    }
}
